/**
 * Algorithm:
 * 
 * 1: Get array of all courses entered 2: Place all the goals that those courses
 * could potentially fulfill 3: Find which goal area has the fewest number of
 * courses that can go towards it 4: Place a course towards that goal area
 * removing all other goal areas it can apply to 5: Loop 3-4 until all courses
 * used up
 */

package com.gelsanalyzer.business;

import java.util.*;

public class MappedList {

    private CourseEntryList cel;
    private int[] optimizedCreditList;
    private int[] creditList;
    private Vector map; // first element is list of courses
    // second element list of goal areas
    private List<CourseEntryItem> CEIList;
    private static final int NUM_OF_GOALS = 12;

    public MappedList(CourseEntryList cel) {
        this.cel = cel;
        map = new Vector();
        CEIList = new ArrayList<CourseEntryItem>();
        creditList = new int[NUM_OF_GOALS];
        optimizedCreditList = new int[NUM_OF_GOALS];
        for ( int i = 0; i < NUM_OF_GOALS; i++ ) {
            creditList[i] = 0;
            optimizedCreditList[i] = 0;
        }
    }

    public void print() {
        for ( int i = 0; i < CEIList.size(); i++ ) {
            System.out.println(CEIList.get(i).getCourse().getCourseDesc() + " "
                    + CEIList.get(i).getCourse() + " Credits: "
                    + CEIList.get(i).getCourse().getCourseCredits()
                    + " Goals it can apply to <"
                    + CEIList.get(i).getGoalarea().toString() + ">");
        }

        System.out.println("\n\nFor the grand finale");
        List<Course> courseList = (List<Course>) map.get(0);
        List<Integer> intList = (List<Integer>) map.get(1);

        for ( int l = 0; l < courseList.size(); l++ ) {
            System.out.println("Course = " + courseList.get(l).getCourseDesc()
                    + " " + courseList.get(l));
            System.out.println("Goal applied to = " + intList.get(l));
            System.out.println("Number of credits applied to that goal = "
                    + courseList.get(l).getCourseCredits() + "\n");

        }
    }

    public void optimize() {
        // first fill up CEIList with everything inside cel
        List<Integer> intList = new ArrayList<Integer>();
        List<Course> cList = new ArrayList<Course>();
        CEIList = cel.getCourseList();
        // Now put all credits in creditList
        for ( int i = 0; i < CEIList.size(); i++ ) {
            for ( int j = 0; j < CEIList.get(i).getGoalarea().size(); j++ ) {
                for ( int k = 0; k < CEIList.get(i).getGoalarea().get(j)
                    .getGoalAsNum().size(); k++ ) {

                    creditList[CEIList.get(i).getGoalarea().get(j)
                        .getGoalAsNum().get(k).intValue()] += CEIList.get(i)
                        .getCourse().getCourseCredits();

                }
            }
        }
        // Find which goal has the least that can possibly fulfill it
        int posOfSmallest;
        for ( int c = 0; c < NUM_OF_GOALS; c++ ) {
            for ( int i = 0; i < CEIList.size(); i++ ) {
                for ( int j = 0; j < CEIList.get(i).getGoalarea().size(); j++ ) {
                    for ( int k = 0; k < CEIList.get(i).getGoalarea().get(j)
                        .getGoalAsNum().size(); k++ ) {
                        posOfSmallest = findFewestGoals();
                        if ( CEIList.get(i).getGoalarea().get(j).getGoalAsNum()
                            .get(k).intValue() == posOfSmallest ) {
                            // Find a course that can meet that goal
                            // Place it towards that goal and make sure to
                            // remove it from
                            // any other goal it could fulfill

                            optimizedCreditList[CEIList.get(i).getGoalarea()
                                .get(j).getGoalAsNum().get(k).intValue()] += CEIList
                                .get(i).getCourse().getCourseCredits();
                            creditList[posOfSmallest] -= CEIList.get(i)
                                .getCourse().getCourseCredits();
                            if ( CEIList.get(i).getGoalarea().get(j)
                                .getGoalAsNum().size() > 1 ) {
                                // we already placed one of its goals, we need
                                // to drop the other
                                int other = (j == 0 ? 0 : 1);
                                creditList[CEIList.get(i).getGoalarea().get(j)
                                    .getGoalAsNum().get(other).intValue()] -= CEIList
                                    .get(i).getCourse().getCourseCredits();
                                /* All the code above me works */
                            }

                            // now just need to link which course gave
                            // optimizedCreditList
                            // its credits
                            cList.add(CEIList.get(i).getCourse());
                            intList.add(CEIList.get(i).getGoalarea().get(j)
                                .getGoalAsNum().get(k));

                        }

                    }
                }
            }
        }
        map.add(cList);
        map.add(intList);
    }

    private int findFewestGoals() { // works
        int smallest = 1000;
        int posOfSmallest = -1;

        for ( int i = 0; i < NUM_OF_GOALS; i++ ) {
            if ( creditList[i] < smallest && creditList[i] > 0 ) {
                posOfSmallest = i;
                smallest = creditList[i];
            }
        }
        return posOfSmallest;
    }

    /**
     * @return the optimizedCreditList
     */
    public int[] getOptimizedCreditList() {
        return optimizedCreditList;
    }

    /**
     * @return the map
     */
    public Vector getMap() {
        return map;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
         for (int i=0; i<CEIList.size(); i++) {
         sb.append(CEIList.get(i).getCourse().getCourseDesc() +
         " " + CEIList.get(i).getCourse() + " Credits: " +
         CEIList.get(i).getCourse().getCourseCredits() +
         " Goals it can apply to <" + CEIList.get(i).getGoalarea().toString()
         + ">\n");
         }
                
        //System.out.println("\n\nFor the grand finale");
        List<Course> courseList = (List<Course>) map.get(0);
        List<Integer> intList = (List<Integer>) map.get(1);
        
        for ( int l = 0; l < courseList.size(); l++ ) {
            sb.append("\nCourse: " + courseList.get(l).getDepartment() + ""
                    + courseList.get(l));
            sb.append("\nDescrption: " + courseList.get(l).getCourseDesc() + "\n");
            sb.append("Goal applied to = " + intList.get(l) + "\n");
            sb.append("Number of credits applied to that goal = "
                    + courseList.get(l).getCourseCredits() + "\n");
        }
        
        return sb.toString();
    }
}
